package logica.locacao;

import java.io.Serializable;
import java.util.HashSet;
import logica.locacao.RegistroDeLocacao.FormaDePagamento;
import logica.util.Data;
import logica.util.GeradorDeCodigo;

/**
 * Extratos possuem informacoes muito mais detalhadas acerca de um Registro de Locacao.
 * Contem aquelas informacoes adicionais que nao sao necessarias posteriormente, por exemplo,
 * no controle de devolucoes.
 * A finalidade principal de um Extrato eh apenas para que dele seja gerado um arquivo PDF.
* @author Equipe Localisa (Usa quem precisa!)
 */

public class Extrato implements Serializable{

	private transient static final long serialVersionUID = 1L;
	private int codigoExclusivo;
	private int codigoDoRegistroDeLocacao = 0;
	private FormaDePagamento formaDePagamento;
	private Data dataLocacao;
	private Data dataDevolucaoAssumidaComoCompromisso;
	private double precoDaDiaria;
	private int qtdeDiariasASeremPagas;
	private int quilometragem;
	private double precoPorQuilometro;
	private double precoDaLocacao;
	private double precoDoSeguro;
	private double precoTotal;
	private String codigoDoCliente;
	private HashSet<String> codigosDosVeiculos;
	private String movimentacao;
	private String movimentacaoParaImpressao;
	
	public Extrato(){
		
		this.codigoExclusivo = GeradorDeCodigo.getCodigo();
		this.codigoDoRegistroDeLocacao = 0;
		this.codigoDoCliente = null;
		this.codigosDosVeiculos = null;
		this.dataLocacao = null;
		this.dataDevolucaoAssumidaComoCompromisso = null;
		this.formaDePagamento = null;
		this.precoDaDiaria = 0;
		this.qtdeDiariasASeremPagas = 0;
		this.quilometragem = 0;
		this.precoPorQuilometro = 0;
		this.precoDaLocacao = 0;
		this.precoDoSeguro = 0;
		this.precoTotal = 0;
		this.movimentacao = null;
		this.movimentacaoParaImpressao = "";
		
	}
	
	/**
	 * @return A movimentacao do extrato, isto eh, todas as informacoes
         * de como foram feitos os calculos para obter o preco final da locacao.
	 */
	
	public String getMovimentacao(){
		return this.movimentacao;
	}

	/**
	 * @return A movimentacao pronta para impressao, considerando informacoes
         * que devem ir para as tabelas dos PDFs.
	 */
	
	public String getMovimentacaoParaImpressao(){
		return this.movimentacaoParaImpressao;
	}
	
	public void setInfoMovimentacao(String informacao){
		this.movimentacao = informacao;
		this.movimentacaoParaImpressao = informacao;
	}
	
	/**
	 * Adiciona uma informacao na movimentacao do extrato.
         * Se esse metodo for chamado pela primeira vez, ele monta um cabecalho
         * do extrato com as informacoes essenciais.
	 * @param A informacao a ser adicionada
	 * @throws Exception Se a informacao for nula ou vazia
	 */
	
	public void addInfo(String informacao) throws Exception{
		if ( informacao.trim().isEmpty() || informacao == null ){
			throw new Exception("\n \t <Informacoes invalidas para o extrato!>");
		}
		if ( this.movimentacao == null ){
			this.movimentacao = "Extrato "+this.getCodigoDoExtrato()+" da locacao "+this.getCodigoDoRegistroDeLocacao()+" realizada pelo cliente "+this.getCodigoDoCliente()+":\n";
			this.movimentacao += "Veiculos alugados: ";
			for ( String codigoVeiculo : this.codigosDosVeiculos ){
				this.movimentacao += codigoVeiculo;
			}
			this.movimentacao += "\nData da locacao: "+this.getDataDeLocacao().getDataPorExtenso();
			if ( this.getDataDeDevolucao() != null ){
				this.movimentacao += "\nCompromisso de devolucao em: "+this.getDataDeDevolucao().getDataPorExtenso();
			}
			else{
				this.movimentacao += "\nData de devolucao nao especificada.";
			}
			this.movimentacao += "\n\nForma de pagamento: "+this.getFormaDePagamento()+"\n";
		}
		this.movimentacaoParaImpressao += informacao+"\n";
		this.movimentacao += informacao+"\n";
	}
	
	/**
	 * @return O codigo exclusivo deste extrato
	 */
	public int getCodigoDoExtrato(){
		return this.codigoExclusivo;
	}
	
	/**
	 * @return O codigo do registro de locacao associado ao extrato
	 */
	public int getCodigoDoRegistroDeLocacao(){
		return this.codigoDoRegistroDeLocacao;
	}
	
	/**
	 * Muda o codigo do registro de locacao descrito pelo extrato.
	 * @param codigo O novo codigo do registro de locacao
	 * @throws Exception Se o novo codigo for menor ou igual a 0
	 */
	
	public void setCodigoDoRegistroDeLocacao(int codigo) throws Exception{
		if ( codigo <=0 ){
			throw new Exception("\n \t <Codigo do registro de locacao invalido!>");
		}
		this.codigoDoRegistroDeLocacao = codigo;
	}
	
	/**
	 * @return O codigo do cliente
	 */
	
	public String getCodigoDoCliente(){
		return this.codigoDoCliente;
	}
	
	/**
	 * Muda o codigo do cliente
	 * @param codigo O novo codigo do cliente
	 * @throws Exception Se o codigo do cliente for nulo ou vazio
	 */
	
	public void setCodigoDoCliente(String codigo) throws Exception{
		if ( codigo == null || codigo.isEmpty()   ){
			throw new Exception("\n \t <Codigo do cliente invalido!>");
		}
		this.codigoDoCliente = codigo;
	}
	
	/**
	 * @return Um conjunto que contem os codigos dos veiculos locados
	 */
	
	public HashSet<String> getCodigosDosVeiculos(){
		return this.codigosDosVeiculos;
	}
	
	/**
	 * Muda o conjunto dos codigos dos veiculos
	 * @param codigos O novo conjunto dos codigos dos veiculos
	 * @throws Exception Se o novo conjunto for nulo
	 */
	
	public void setCodigosDosVeiculos(HashSet<String> codigos) throws Exception{
		if ( codigos == null ){
			throw new Exception("\n \t <Codigos dos veiculos invalidos!");
		}
		this.codigosDosVeiculos = codigos;
	}
	
	
	/**
	 * @return A data de locacao
	 */
	public Data getDataDeLocacao(){
		return this.dataLocacao;
	}
	
	
	/**
	 * Muda a data de locacao
	 * @param dataLocacao A nova data de locacao
	 * @throws Exception Se a nova data for nula
	 */
	public void setDataDeLocacao(Data dataLocacao) throws Exception{
		if ( dataLocacao == null ){
			throw new Exception("\n \t <Data de locacao invalida!>");
		}
		this.dataLocacao = dataLocacao;
	}
	
	/**
	 * @return A data de devolucao
	 */
	
	public Data getDataDeDevolucao(){
		return this.dataDevolucaoAssumidaComoCompromisso;
	}
	
	/**
	 * Muda a data de devolucao
	 * @param dataDevolucao A nova data de devoucao
	 * @throws Exception Se a nova data for nula
	 */
	
	public void setDataDeDevolucao(Data dataDevolucao) throws Exception{
		if ( dataDevolucao == null ){
			throw new Exception("\n \t <Data de devolucao invalida!>");
		}
		this.dataDevolucaoAssumidaComoCompromisso = dataDevolucao;
	}
		
	/**
	 * @return A constante FormaDePagamento que representa a forma de pagamento
	 */
	public FormaDePagamento getFormaDePagamento(){
		return this.formaDePagamento;
	}
	
	
	/**
	 * Muda a forma de pagamento
	 * @param forma A nova forma de pagamento
	 * @throws Exception Se a nova forma de pagamento for nula
	 */
	public void setFormaDePagamento(FormaDePagamento forma) throws Exception{
		if ( forma == null ){
			throw new Exception("\n \t <Forma de pagamento invalida!>");
		}
		this.formaDePagamento = forma;
	}
	
	/**
	 * @return O preco da diaria do plano escolhido
	 */
	
	public double getPrecoDaDiaria(){
		return this.precoDaDiaria;
	}
	
	/**
	 * Muda o preco da diaria
	 * @param preco O novo preco da diaria
	 * @throws Exception Se o novo preco for menor que 0
	 */
	public void setPrecoDaDiaria(double preco) throws Exception{
		if ( preco <= 0 ){
			throw new Exception("\n \t <Preco da diaria invalido!>");
		}
		this.precoDaDiaria = preco;
	}
	
	/**
	 * @return A quantidade de diarias a serem pagas
	 */
	
	public int getQtdeDiariasASeremPagas(){
		return this.qtdeDiariasASeremPagas;
	}
	
	/**
	 * Muda a quantidade de diarias a serem pagas
	 * @param qtde A nova quantidade de diarias
	 * @throws Exception Se a nova quantidade de diarias for menor ou igual a 0
	 */
	
	public void setQtdeDiariasASeremPagas(int qtde) throws Exception{
		if ( qtde < 0 ){
			throw new Exception("\n \t <Quantidade de diarias a serem pagas invalida!>");
		}
		this.qtdeDiariasASeremPagas = qtde;
	}

	/**
	 * @return A quilometragem percorrida do veiculo
	 */
	
	public int getQuilometragem(){
		return this.quilometragem;
	}
	
	/**
	 * Muda a quilometragem percorrida do veiculo
	 * @param quilometragem A nova quilometragem
	 * @throws Exception Se a nova quilometragem for menor ou igual a 0
	 */
	
	public void setQuilometragem(int quilometragem) throws Exception{
		if ( quilometragem <=0 ){
			throw new Exception("\n \t <Quilometragem invalida!>");
		}
		this.quilometragem = quilometragem;
	}
	
	/**
	 * @return O preco da locacao por quilometro
	 */
	
	public double getPrecoPorQuilometro(){
		return this.precoPorQuilometro;
	}
	
	/**
	 * Muda o preco da locacao por quilometro
	 * @param preco O novo preco da locacao
	 * @throws Exception Se o novo preco da locacao por quilomero for menor que 0
	 */
	
	public void setPrecoPorQuilometro(double preco) throws Exception{
		if ( preco <=0 ){
			throw new Exception("\n \t <Preco por quilometro invalido!>");
		}
		this.precoPorQuilometro = preco;
	}
	
	/**
	 * @return O preco da locacao
	 */
	
	public double getPrecoDaLocacao(){
		return this.precoDaLocacao;
	}

	/**
	 * Muda o preco da locacao
	 * @param preco O novo preco da locacao
	 * @throws Exception Se o novo preco for menor que 0
	 */
	
	public void setPrecoDaLocacao(double preco) throws Exception{
		if ( preco < 0 ){
			throw new Exception("\n \t <Preco da locacao invalido!>");
		}
		this.precoDaLocacao = preco;
	}
	
	/**
	 * @return O preco do seguro
	 */
	
	public double getPrecoDoSeguro(){
		return this.precoDoSeguro;
	}
	
	/**
	 * Muda o preco do seguro
	 * @param preco O novo preco do seguro
	 * @throws Exception Se o novo preco for menor que 0
	 */
	
	public void setPrecoDoSeguro(double preco) throws Exception{
		if ( preco < 0 ){
			throw new Exception("\n \t <Preco do seguro invalido!>");
		}
		this.precoDoSeguro = preco;
	}
	
	/**
	 * @return O preco total da movimentacao
	 */
	
	public double getPrecoTotal(){
		return this.precoTotal;
	}
	
	/**
	 * Muda o preco total da movimentacao
	 * @param preco O novo preco
	 * @throws Exception Se o novo preco for menor que 0
	 */
	
	public void setPrecoTotal(double preco) throws Exception{
		if ( preco <= 0 ){
			throw new Exception("\n \t <Preco total da locacao invalido!>");
		}
		this.precoTotal = preco;
	}
	
}